#include "sh.h"
#include <string.h>

SH_CMD_FN(_cmd1_fn);   // 定义一个命令函数
SH_CMD_FN(_cmd2_fn);   // 定义一个命令函数
SH_CMD_FN(_cmd3_4_fn); // 定义一个命令函数

SH_CMD_CP_FN(_cmd1_tab);   // 定义一个命令补全函数，当完整的命令被输入后，再次按下 Tab 键会调用该函数
SH_CMD_CP_FN(_cmd2_tab);   // 定义一个命令补全函数，当完整的命令被输入后，再次按下 Tab 键会调用该函数
SH_CMD_CP_FN(_cmd3_4_tab); // 定义一个命令补全函数，当完整的命令被输入后，再次按下 Tab 键会调用该函数

SH_DEF_SUB_CMD(                                                       // 定义一个子命令列表
    _sub_2,                                                           // 子命令列表命名
    SH_SETUP_CMD("cmd3", "cmd3 的帮助信息", _cmd3_4_fn, _cmd3_4_tab), // 使用 SH_SETUP_CMD 可以定义一个命令字段
);

SH_DEF_SUB_CMD(                                                   // 定义一个子命令列表
    _sub_1,                                                       // 子命令列表命名
    SH_SETUP_CMD("cmd2", "cmd2 的帮助信息", _cmd2_fn, _cmd2_tab), // 使用 SH_SETUP_CMD 可以定义一个命令字段
    SH_SETUP_CMD("sub", "sub 的帮助信息", NULL, _sub_2),          // 子命令也可以继续定义子命令
);

SH_DEF_CMD(                                                       // 定义一个根命令列表
    _register_cmd,                                                // 根命令列表命名
    SH_SETUP_CMD("cmd1", "cmd1 的帮助信息", _cmd1_fn, _cmd1_tab), // 使用 SH_SETUP_CMD 可以定义一个命令字段
    SH_SETUP_CMD("set", "set 的帮助信息", NULL, _sub_1),          // 如果即值为 NULL 时，表示有子命令
);

SH_DEF_SUB_CMD(                                                       // 定义一个子命令列表
    _sub_4,                                                           // 子命令列表命名
    SH_SETUP_CMD("cmd4", "cmd3 的帮助信息", _cmd3_4_fn, _cmd3_4_tab), // 使用 SH_SETUP_CMD 可以定义一个命令字段
);

SH_DEF_SUB_CMD(                                          // 定义一个子命令列表
    _sub_3,                                              // 子命令列表命名
    SH_SETUP_CMD("sub", "sub 的帮助信息", NULL, _sub_4), // 子命令也可以继续定义子命令
);

SH_DEF_CMD(                                              // 定义一个根命令列表
    _register_cmd2,                                      // 根命令列表命名
    SH_SETUP_CMD("set", "set 的帮助信息", NULL, _sub_3), // 如果即值为 NULL 时，表示有子命令
);

SH_CMD_FN(_cmd1_fn)
{
    sh_echo(sh_hdl, "命令被执行\r\n");
    for (int i = 0; i < argc; i++)
    {
        sh_echo(sh_hdl, "参数 %d: %s\r\n", i + 1, argv[i]);
    }
    return 0;
}

SH_CMD_FN(_cmd2_fn)
{
    sh_echo(sh_hdl, "命令被执行\r\n");
    for (int i = 0; i < argc; i++)
    {
        sh_echo(sh_hdl, "参数 %d: %s\r\n", i + 1, argv[i]);
    }
    return 0;
}

SH_CMD_FN(_cmd3_4_fn)
{
    sh_echo(sh_hdl, "命令被执行\r\n");
    for (int i = 0; i < argc; i++)
    {
        sh_echo(sh_hdl, "参数 %d: %s\r\n", i + 1, argv[i]);
    }
    return 0;
}

SH_CMD_CP_FN(_cmd1_tab)
{
    if (argc + flag == 1)
    {
        /**
         * 使用 sh_completion_param() 函数定义命令的补全信息
         */
        sh_cp_param_t const param[] = {
            {"opt1", .help = "选项 1 的帮助信息"},
            {"opt2", .help = "选项 2 的帮助信息"},
            {"opt3", .help = "选项 3 的帮助信息"},
            {NULL},
        };
        sh_completion_param(sh_hdl, param);
    }
}

SH_CMD_CP_FN(_cmd2_tab)
{
    if (argc + flag == 1)
    {
        /**
         * 使用 sh_completion_resource() 函数定义命令的补全信息
         * 该函数可以多次调用，每次调用添加一个补全项。
         * 其中 arg_str 为 NULL 时表示按当前命令行自动填充
         */
        sh_completion_resource(sh_hdl, NULL, "opt1", "选项 1 的帮助信息");
        sh_completion_resource(sh_hdl, NULL, "opt2", "选项 2 的帮助信息");
        sh_completion_resource(sh_hdl, NULL, "opt3", "选项 3 的帮助信息");
    }
}

SH_CMD_CP_FN(_cmd3_4_tab)
{
    if (argc + flag == 1)
    {
        int lev = 0;
        const char *arg_str = argv[0];
        if (arg_str != NULL)
        {
            const char *str = strchr(argv[0], ':');
            while (str != NULL)
            {
                arg_str = str + 1;
                str = strchr(arg_str, ':');
                lev++;
            }
            str = strchr(arg_str, '/');
            while (str != NULL)
            {
                arg_str = str + 1;
                str = strchr(arg_str, '/');
                lev++;
            }
        }

        /**
         * 使用 sh_completion_resource() 函数定义命令的补全信息
         * 该函数可以多次调用，每次调用添加一个补全项。
         * 其中 arg_str 不为 NULL 时，表示按指定的信息填充
         */
        if (lev == 0)
        {
            sh_completion_resource(sh_hdl, arg_str, "path1:", "路径 1");
            sh_completion_resource(sh_hdl, arg_str, "path2:", "路径 2");
        }
        else if (lev == 1)
        {
            sh_completion_resource(sh_hdl, arg_str, "dir1/", "目录 1");
            sh_completion_resource(sh_hdl, arg_str, "dir2/", "目录 2");
            sh_completion_resource(sh_hdl, arg_str, "dir3/", "目录 3");
        }
        else if (lev == 2)
        {
            sh_completion_resource(sh_hdl, arg_str, "dir-n/", "目录 n");
        }
        else
        {
            sh_completion_resource(sh_hdl, arg_str, "file1 ", "文件 1");
            sh_completion_resource(sh_hdl, arg_str, "file2 ", "文件 2");
            sh_completion_resource(sh_hdl, arg_str, "file3 ", "文件 3");
        }
    }
}

void sample_shell(void)
{
    sh_register_cmd(&_register_cmd);
    sh_register_cmd(&_register_cmd2);
}
